Repository navigation
Conversation
The Remote server rewrote the whole trusted-device file from a copy it had read earlier (pairing, last-seen updates, idle expiry), while the desktop revokes a device by rewriting the same file. A server write that landed after a revoke put the device back, and its cookie or relay credential worked again. The server now applies each change, one at a time, to a fresh read of the file and never writes back a device that is no longer on disk. A read and a write in two processes can still straddle a revoke, so the desktop also lists the revoked credential hash in revoked-devices.json, which only the desktop writes. The server refuses every listed credential, drops it from the trusted file on its next write, and fails closed when the list cannot be read. Signed-off-by: Hao0321 <126182090+Hao0321@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YQbUWKu73ka7dZ58vWVzgY
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
The Remote server (
src/remote/server.ts) rewrote the whole trusted-device file from a copy it had read earlier. It did this on pairing (LAN and relay), onlastSeenupdates and on idle-expiry cleanup. The desktop'srevoke_mobile_devicerewrites the same file. If a server write landed just after a revoke, the device was written back and its credential worked again. #48 added more of these write paths.updateTrustedDevices. It re-reads the file immediately before writing and applies only its own change: add the newly paired device, updatelastSeenof an entry that is still on disk, or drop an expired entry. It never writes back a device that is no longer on disk.revoke_mobile_devicefirst records the revoked credential's hash inrevoked-devices.json, next to the trusted file, and only then rewrites the trusted file.write_remote_json_atomicand holds themobile_remotelock, so two revokes cannot lose each other's entry.docs/SECURITY_MODEL.md: the Revocation bullet now describes both mechanisms..github/workflows/source-ci.yml: the Linux job runs only named Rust tests, so the new Rust test is added to its existing remote-state step. Job names are unchanged.I rejected two alternatives:
User journey and platform
Mobile Remote on the desktop. After you revoke a device in the Remote dialog, its next request is refused, even if it was active at the same moment. Other devices are unaffected.
Validation
src/remote/revocation.test.ts: the server's read is held open on a FIFO so that a desktop-style revoke lands between the server's read and its write.server.tsonmain, 7 of 8 tests fail (the revoked device gets200).mkfifo.npx vitest run src/remote/: 76 passed, 1 skipped (that skip also exists onmain).npm test: 280 files and 2176 tests passed.npm run typecheck,npm run build: passed.npm run source:scanandnpm run source:verify:self-test: GREEN.scripts/architecture-check.ts: ALLOW.cargo test --locked --manifest-path src-tauri/Cargo.toml --features community-desktop,tauri/custom-protocol revoking_a_mobile_device_lists_its_credential_before_dropping_itpassed.200before the revoke and401after. It stayed401when the entry was put back, and another device stayed200.Remaining limits:
Security and provenance
No new dependencies, network access or process execution.
New file write:
revoked-devices.jsonin the desktop's existing private remote-state directory. It is written only by the desktop, owner-only and atomic, and holds SHA-256 credential hashes only, never credentials.No secrets or private footage.
DCO
The commit has a
Signed-off-by:trailer.🤖 Generated with Claude Code
https://claude.ai/code/session_01YQbUWKu73ka7dZ58vWVzgY
Generated by Claude Code